package com.dongzili.easyes.common.mybatisplus;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

public class PropertyQueryWrapper<T> extends AbstractWrapper<T, String, PropertyQueryWrapper<T>> implements Query<PropertyQueryWrapper<T>, T, String> {
    protected final SharedString sqlSelect;
    private boolean checkSqlInjection;
    private PropertyDbTypeEnum propertyDbTypeEnum = PropertyDbTypeEnum.NONE;

    public PropertyQueryWrapper() {
        this((T) null);
    }
    public PropertyQueryWrapper(PropertyDbTypeEnum propertyDbTypeEnum) {
        this((T) null);
        this.propertyDbTypeEnum = propertyDbTypeEnum;
    }

    public PropertyQueryWrapper(T entity) {
        this.sqlSelect = new SharedString();
        super.setEntity(entity);
        super.initNeed();
    }

    public PropertyQueryWrapper(Class<T> entityClass) {
        this.sqlSelect = new SharedString();
        super.setEntityClass(entityClass);
        super.initNeed();
    }

    public PropertyQueryWrapper(T entity, String... columns) {
        this.sqlSelect = new SharedString();
        super.setEntity(entity);
        super.initNeed();
        this.select(columns);
    }

    private PropertyQueryWrapper(T entity, Class<T> entityClass, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString paramAlias, SharedString lastSql, SharedString sqlComment, SharedString sqlFirst) {
        this.sqlSelect = new SharedString();
        super.setEntity(entity);
        super.setEntityClass(entityClass);
        this.paramNameSeq = paramNameSeq;
        this.paramNameValuePairs = paramNameValuePairs;
        this.expression = mergeSegments;
        this.paramAlias = paramAlias;
        this.lastSql = lastSql;
        this.sqlComment = sqlComment;
        this.sqlFirst = sqlFirst;
    }

    public PropertyQueryWrapper<T> checkSqlInjection() {
        this.checkSqlInjection = true;
        return this;
    }

    protected String columnToString(String column) {
        if (this.checkSqlInjection && SqlInjectionUtils.check(column)) {
            throw new MybatisPlusException("Discovering SQL injection column: " + column);
        } else {
            return column;
        }
    }

    public PropertyQueryWrapper<T> select(boolean condition, List<String> columns) {
        if (condition && CollectionUtils.isNotEmpty(columns)) {
            this.sqlSelect.setStringValue(String.join(",", columns));
        }

        return this.typedThis;
    }

    public PropertyQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {
        super.setEntityClass(entityClass);
        this.sqlSelect.setStringValue(TableInfoHelper.getTableInfo(this.getEntityClass()).chooseSelect(predicate));
        return this.typedThis;
    }

    public String getSqlSelect() {
        return this.sqlSelect.getStringValue();
    }

    public PropertyLambdaWrapper<T> lambda() {
        System.out.println("生成lambda");
        return new PropertyLambdaWrapper<>(propertyDbTypeEnum, this.getEntity(), this.getEntityClass(), this.sqlSelect, this.paramNameSeq, this.paramNameValuePairs, this.expression, this.paramAlias, this.lastSql, this.sqlComment, this.sqlFirst);
    }
//    public PropertyLambdaWrapper<T> lambda(PropertyDbTypeEnum dbTypeEnum) {
//        System.out.println("生成lambda");
//        return new PropertyLambdaWrapper<>(dbTypeEnum, this.getEntity(), this.getEntityClass(), this.sqlSelect, this.paramNameSeq, this.paramNameValuePairs, this.expression, this.paramAlias, this.lastSql, this.sqlComment, this.sqlFirst);
//    }

    protected PropertyQueryWrapper<T> instance() {
        return new PropertyQueryWrapper<>(this.getEntity(), this.getEntityClass(), this.paramNameSeq, this.paramNameValuePairs, new MergeSegments(), this.paramAlias, SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString());
    }

    public void clear() {
        super.clear();
        this.sqlSelect.toNull();
    }


}